#ifndef _GAME_
#define _GAME_

#include "EntityManager.hpp"
#include "LevelManager.hpp"
#include "StaticModel.hpp"
#include "Water.hpp"
#include "InputStruct.hpp"
#include "ParticleSystem.hpp"
#include "Text.hpp"
#include "Sound.hpp"
#include <GLFW/glfw3.h> // to capture and release mouse

#include <list>
#include <vector>
#include <random>
#include <memory>

using namespace std;

class Particle;
class ParticleEmitter;
class ConfigFile;

class Game
{
public:
	Game(ConfigFile& config, int screen_width, int screen_height);

	~Game();

	//draws the whole scene ready for the display
	void DrawScene();

	EntityManager* getEntityManager(){return &m_EntityManager;}

	void start();
	bool isOver();

	void loadLevel(int level);
	bool allBlocksDestroyed();
	void incrementScore(int);
	void decrementBalls(){m_balls--;};
	void extraBall(){m_balls++;};

	bool onUpdate(float time, void* window); // returns if the game should be ended

	int getScore(){ return m_score; }
	int getLevel(){ return m_actualLevel; }
	int getBalls(){ return m_balls; }
	int getMaxCurrentBalls() { return m_max_current_balls; }

	//different camera settings
	void CameraSetup_Above();
	void CameraSetup_Behind();
	void CameraSetup_Free();

	int cameraMode;
	void AddParticleSystem(ParticleSystem *pat) {m_ParticleSystems.push_back(pat); }

	void SetScreenSize(int width, int height);

	void PlaySound(string name, int number=-1); // number=-1 plays random sound

	std::mt19937 rnd;
private:
	friend class Water;
	void AddSound(string name);
	void RenderEntities();//renders a single pass, call this after setting up camera and other stuff
	void CenterText(Text* t, glm::vec2 screen_size);

	ConfigFile& m_Config;

	TextManager m_TextManager;
	Text* m_TextScore;
	Text* m_TextLevel;
	Text* m_TextBalls;
	Text* m_TextStartup;
	Text* m_TextLaunch;
	Text* m_TextLose;

	SoundManager m_SoundManager;
	map<string, vector<unique_ptr<SoundFile>>> m_Sounds;
	float m_Volume;
	unique_ptr<SoundController> m_BgMusic;
	unique_ptr<SoundController> m_WinSound;

	EntityManager m_EntityManager;
	Water m_Water;
	list<ParticleSystem*> m_ParticleSystems;

	int m_score;
	int m_actualLevel;
	int m_balls;
	int m_max_current_balls; // which the player can start, ball launcher blocks are not affected by this

	bool gameOver;
	int difficulty;
	LevelManager levelManager;

	StaticModel m_SkySphere;
	StaticModel m_World;
	StaticModel m_Trees;

	float m_MouseSensitivity;
	bool m_MouseCaptured;
	enum class GameState { startup, initial_capture, running, paused};
	GameState m_GameState;
	float m_NewLevelCounter;

};

#endif // _GAME_
